#pragma once


//entity_removed_from_update_list
MessagePacket * game_entity_removed_from_update_list( MessagePacket * data)
{
	Entity2 * sender = (Entity2*)data->sender;
	//printf("entity removed from update list");
	sender->_vel =  v2(-sender->_vel.x, -sender->_vel.y);
	
	//this is causing crashes...
	//entity_set_pos(sender, entity_get_pos(sender) + sender->_vel*0.1);
	//entity_update_list_update_entity_check( game_get()->_entitys->update_list, sender);
	return 0;
}

void game_destroy(Game2 * game)
{
	//move this into global list
	std::vector<Entity2*> entitys = game->_entitys->global_list->list._entitys;
	for (std::vector<Entity2*>::iterator it = entitys.begin(); it != entitys.end(); ++it)
	{
		entity_remove((*it),game->_router,game->_entitys, false);
	}

	MessageRouter__Clear(game->_router);
}

void game_setup(Game2 * game)
{
	MessageRouter *	router = game->_router;

	//Create message hooks
	MessageRouter_RegisterTriggerCallback(router,entity_move_listener,"on_move");
	MessageRouter_RegisterTriggerCallback(router,entity_grid_on_removed,"entity_removed");
	MessageRouter_RegisterTriggerCallback(router,entity_update_list_on_removed,"entity_removed");

	MessageRouter_RegisterTriggerCallback(router,global_entity_list__on_created,"entity_created");
	MessageRouter_RegisterTriggerCallback(router,global_entity_list__on_removed,"entity_removed");

	MessageRouter_RegisterTriggerCallback(router,game_entity_removed_from_update_list,
											"entity_removed_from_update_list");
	srand(0);
	//Create entitys
	for (int i = 0; i < 15; i++	)
	{
		for (int j = 0; j <1; j++)
		{
			//V2 spacing = 
			V2 pos = {-3 + 1.5f*(i),-3 + 0.5f*((j))};

			Entity2 * e = temp_create_new_entity(router,game->_entitys,pos,v2(1,1));
			//e->_vel.x = 5.0f;
			
			//e->_vel.x = (float)(rand()%100)/100.0f;
			e->_vel.y = (float)(20.0f);
		}
	}
	
	//Set viewport position
	game->_viewport->pos = v2(-5,-5);
}

bool removed = 0;

bool game_run(Game2 * game, float dt, GamePartitionMethods methods, GameGraphicMethods draw )
{
	//Shout(game->_router, game, "game_update"); 

	//render rect around viewport
	Rect viewport_bounds = viewport_get_world_extents(game->_viewport);
	Rect screen_viewport_bounds = viewport_to_screen(viewport_bounds, game->_viewport);

	draw.AddRectFillSS(screen_viewport_bounds,64,0,64,72);

	//game->_viewport->pos.x += (SDL_GetTicks() < 10000 ? 0.05f : -0.05f) * (1+sin(SDL_GetTicks() / 100.0f));

	counter_start(game->_counter, COUNT_ID::C_viewport_update);
	methods.update_sim_list_from_viewport(game);
	counter_end(game->_counter, COUNT_ID::C_viewport_update);

	std::vector<Entity2*> update_entitys = methods.simulated_callback(game); //active_callback(game);

#if 0
	if (SDL_GetTicks() > 1000 * 4 && removed == 0){
		std::vector<Entity2*>::iterator remove_ent_iter;
		int dead_count = 0;
		removed = 1;
		for (remove_ent_iter = update_entitys.begin();dead_count < 20 && remove_ent_iter != update_entitys.end(); remove_ent_iter++)	{
			
			entity_remove(*remove_ent_iter, game->_router,game->_entitys);
			dead_count++;
		}
	}
#endif

	draw.Begin();
	std::vector<Entity2*>::iterator ent_update_iter;
	for (	ent_update_iter = update_entitys.begin();
			ent_update_iter != update_entitys.end();
			ent_update_iter++)
	{
		counter_start(game->_counter,COUNT_ID::C1);
		V2 ent_pos = entity_get_pos(*ent_update_iter);
		V2 ent_size = entity_get_size(*ent_update_iter);

		/*
			Think about proper collision!!
			E.g. EnterCollision
			LeaveCollision
			InCollision

			Mud:
				enter - change animation
				during - change move speed
				leave - change animation

		*/
		bool collides = false;
		bool found_self = false;
		bool active = (*ent_update_iter)->_active;	

		if (active)	{
			std::vector<Entity2*> collision_entiys = methods.region_callback(game,rect_centre(ent_pos,ent_size));

			std::vector<Entity2*>::iterator collision_ent_iter;
			for (collision_ent_iter = collision_entiys.begin();
				 collision_ent_iter != collision_entiys.end();
				 collision_ent_iter++)
			{
				V2 c_pos = entity_get_pos(*collision_ent_iter);
				V2 c_size = entity_get_size(*collision_ent_iter);

				if ((*ent_update_iter)->_id == (*collision_ent_iter)->_id){
					found_self = true;
					continue;
				}
				V2 collision_vector = {};
				if (math_rect_overlap(c_pos, c_pos + c_size, ent_pos, ent_pos + ent_size)){
					collides = true;
					collision_vector = c_pos - ent_pos;
				}
				
#if 1
				float fudge = 0.5 + 3.0f*dt*dt;
				(*ent_update_iter)->_vel = (*ent_update_iter)->_vel - ((collision_vector)*dt*10*fudge);
#endif			
				
				//entity_set_pos(*ent_update_iter,ent_pos - collision_vector );
			}
			
		}
		counter_end(game->_counter,COUNT_ID::C1);

		counter_start(game->_counter, COUNT_ID::C2);
		V2 ent_screen_point = viewport_to_screen_space(ent_pos,game->_viewport);
		Rect ent_bounds = {ent_screen_point,ent_screen_point +  vieport_to_screen_scale(ent_size)};
		draw.AddRectFillSS(ent_bounds,120,collides?50:250,active?50:250,255);

		if(active)
		{
			update_entity((*ent_update_iter),dt);
		}
		counter_end(game->_counter, COUNT_ID::C2);
	}
	counter_start(game->_counter, COUNT_ID::C3);
	
	/*
	SDL_Event event;
	while(SDL_PollEvent(&event))
	{

	}
	*/

	draw.Render();
	draw.End();
	counter_end(game->_counter, COUNT_ID::C3);
	return false;
}


#if 0
	/* Should this go here? or back into main? */
	vector<pair<string, MessageCallbackFnPtr> > callback_map;
	callback_map.push_back(pair<string,MessageCallbackFnPtr>("on_move", entity_move_listener));
	callback_map.push_back(pair<string,MessageCallbackFnPtr>("entity_removed", entity_grid_on_removed));
	callback_map.push_back(pair<string,MessageCallbackFnPtr>("entity_removed", entity_update_list_on_removed));

	//global_entity_list__on_created
	callback_map.push_back(pair<string,MessageCallbackFnPtr>("entity_created",global_entity_list__on_created));
	callback_map.push_back(pair<string,MessageCallbackFnPtr>("entity_removed",global_entity_list__on_removed));


	for (int map_index = 0; map_index < callback_map.size(); map_index++)
	{
		MessageRouter_RegisterTriggerCallback(router,
			callback_map.at(map_index).second,		//callback ptr function
			callback_map.at(map_index).first);		//callback string name
	}
#endif